using Godot;
using System;
using System.Collections.Generic;

public partial class Game : Node2D
{
	[Export]
	private Label info;
	[Export]
	private Node2D pathes;
	[Export]
	private Board board;
	[Export]
	private Node2D selection;
	[Export]
	private float selectionOffset;
	[Export]
	private PackedScene pathNode;

	private Vector2I? selecting = null;
	private List<Vector2I> selectingAvaliables = null;
	public Entity[,] entitySlot = new Entity[9, 10];

	private int currentTeam = 0;

	private readonly Queue<Node2D> pathNodes = new();

	public override void _Ready()
	{
		selection.Visible = false;
		board.OnGridClick += OnBoardClick;

		info.Text = $"Current {(currentTeam == 0 ? "Black" : "Red")}";
	}

	public void SetEntity(int x, int y, Entity entity)
	{
		if (!Rule.OnBoard(x, y) || entitySlot[x, y] != null) return;

		entity.Position = board.FramePos + board.UnitSize * new Vector2(x, y);
		entitySlot[x, y] = entity;
		AddChild(entity);
	}

	public void OnBoardClick(int x, int y)
	{
		if (!Rule.OnBoard(x, y)) return;

		if (selecting is Vector2I s && selectingAvaliables?.Contains(new(x, y)) == true)
		{
			if (entitySlot[x, y] != null)
			{
				GD.Print($"{s} ate ({x}, {y})");
				entitySlot[x, y].QueueFree();
			}

			MoveEntity(s, new(x, y));

			currentTeam = currentTeam == 0 ? 1 : 0;

			info.Text = $"Current {(currentTeam == 0 ? "Black" : "Red")}";

			selecting = null;
			selection.Visible = false;

			RecyclePathNodes();
		}
		else if (entitySlot[x, y] is Entity chess && chess.team == currentTeam)
		{
			selecting = new(x, y);
			selectingAvaliables = entitySlot[x, y].entity?.GetNextPos(this, entitySlot[x, y].team, selecting.Value);

			RecyclePathNodes();
			foreach (var p in selectingAvaliables) 
			{
				var node = ObtainPathNode();
				if (entitySlot[p.X, p.Y] != null)
				{
					node.Modulate = Color.FromHtml("#00ff00ff");
				}
				else
				{
					node.Modulate = Color.FromHtml("#ffffffff");
				}
				node.Position = board.GetGridPosition(p.X, p.Y);
				pathes.AddChild(node);
			}

			selection.Visible = true;
			selection.Position = board.GetGlobalPosition(x, y) + new Vector2(0, selectionOffset);
		}
	}

	private void RecyclePathNodes()
	{
		foreach (var node in pathes.GetChildren())
		{
			pathes.RemoveChild(node);
			pathNodes.Enqueue(node as Node2D);
		}
	}

	private Node2D ObtainPathNode() => pathNodes.TryDequeue(out var node) ? node : pathNode.Instantiate<Node2D>();

	public void MoveEntity(Vector2I from, Vector2I to)
	{
		GD.Print($"move chess from {from} to {to}");

		entitySlot[to.X, to.Y] = entitySlot[from.X, from.Y];
		entitySlot[from.X, from.Y] = null;

		entitySlot[to.X, to.Y].Position = board.GetGridPosition(to.X, to.Y);
	}

	public Side GetTeamSide(int team) => team == 1 ? Side.Up : Side.Down;
}
